#ifndef _RETRO_FRAME
#define _RETRO_FRAME

namespace Retro
{
  namespace Creator
  {
    enum FrameAction
    {
      FrameInvalid,
      FrameNewProject,
      FrameNewGridMap,
      FrameNewSpriteMap,
      FrameNewTexture,
      FrameNewScript,
      FrameOpenProject,
      FrameSaveResource,
      FrameSaveAll,
      FrameCloseProject,
      FrameCloseResource,
      FrameCloseAll,
      FrameEditProject,
      FrameEditResource,
      FrameUndo,
      FrameRedo,
      FrameRevert,
      FrameExit,
      FrameShowOptions,
      FrameShowAbout,
      FrameAttachDebugger,
      FrameEmbedPlayer,
      FrameRunScript,
      FrameRunProject,
      FrameStopProject,
      FrameHideToolBar,
      FrameHideStatusBar,
      FrameHideMenuBar,
      FrameNextTab,
      FramePrevTab,
      FrameThemeFirst,
      FrameThemeDefault = FrameThemeFirst + ThemeDefault - ThemeFirst,
      FrameThemeOrange  = FrameThemeFirst + ThemeOrange  - ThemeFirst,
      FrameThemeBlue    = FrameThemeFirst + ThemeBlue    - ThemeFirst,
      FrameThemeLast    = FrameThemeFirst + ThemeLast    - ThemeFirst,
      FrameWindowFirst,
      FrameWindowLast   = FrameWindowFirst + 255,
      FrameInternal,
    };

    enum FrameTabType
    {
      FrameTabInvalid,
      FrameTabEditor,
      FrameTabDebugger,
    };

    enum FrameComponent
    {
      FrameCreator,
      FrameScriptor,
      FrameEditor,
    };

    class Frame : Windows::Window
    {
    private:
      struct DocumentState
      {
        INT id;
        INT type;
      };

      static Frame*     pFrame;

      struct {
        GUI::Container  document;
        GUI::Container  tiles;
        GUI::Container  script;
        GUI::Container  browser;
        GUI::Container  sprites;
        GUI::Container  commands;
        GUI::Container  info;
        GUI::Container  history;
      } containers;

      GUI::Container*   mActiveContainer;

      Dialog::EditGridMap     editGrid;
      Dialog::EditSpriteMap   editSprite;
      Dialog::EditProject     editProject;
      Dialog::EditTexture     editTexture;
      Dialog::EditScript      editScript;
      Dialog::Options         mOptions;
      Dialog::About           mAbout;

      Toolbox::Browser        mBrowser;
      Toolbox::Selector       mSelector;
      Toolbox::Scriptor       mScriptor;
      Toolbox::SpriteList     mSprites;
      Toolbox::Debugger       mDebugger;

      union
      {
        Editor::MapEditor*    mEditorMap;
        Editor::GridEditor*   mEditorGrid;
        Editor::SpriteEditor* mEditorSprite;
        Editor::ScriptEditor* mEditorScript;
        Editor::EditorBase*   mEditor;
      };

      Editor::EditSurface mSurface;

      TabHeader       mTabs;
      ToolBar         mEditorbar;
      ToolBar         mToolbar;
      Button          btnNew;
      Button          btnOpen;
      PictureBox      picLogo;
      Label           lblWelcome;
      Label           mStatusbar;
      LayoutElement   mLayout;
      LayoutElement*  mWorkspace;
      Gdip::Font      mStatusFont;
      Gdip::Font      mWelcomeFont;
      Gdip::Bitmap    mWelcomeLogo;

      Hierarchy   mHierarchy;
      FrameState  mState;
      ThemeStyle  mTheme;

      WrapWnd             mPlayer;
      PROCESS_INFORMATION mPlayerInfo;

      Data::RetroProject  project;
      Data::Resource*     mResource;
      TCHAR               projPath[MAX_PATH];
      OPENFILENAME        projOpen;
      BOOL                mLoading;

      TCHAR   mStatusBuffer[100];
      TCHAR   mStatusMessage[100];

      LARGE_INTEGER   mStartTime;
      LARGE_INTEGER   mEndTime;
      LARGE_INTEGER   mFreqTime;

      Menu    mMenuMain;
      Menu    mMenuFile;
      Menu    mMenuEdit;
      Menu    mMenuWindow;
      Menu    mMenuHelp;
      Menu    mMenuProject;
      Menu    mMenuScript;
      Menu    mMenuRes;
      Menu    mMenuTheme;
      Menu    mMenuNew;
      Menu    mMenuSave;

      VOID    loadLayout();
      VOID    saveLayout();
      VOID    loadDocuments();
      VOID    saveDocuments();
      VOID    loadScript();
      VOID    saveScript();
      VOID    loadOptions();
      VOID    showWelcome();

      VOID    selectTab(TabItem* iValue);
      VOID    closeTab(TabItem* iValue);
      VOID    uninitTab();
      VOID    uninitDocuments();
      VOID    selectEditor(Editor::EditorBase* iValue);
      INT     findResourceTab(Data::Resource* iValue);

      Editor::EditorBase* getEditor(Data::ResourceType iType);

      static INT    windowToID(HWND window);
      static HWND   IDtoWindow(INT id);
      static PCTSTR tabTextGetter(TabItem* iItem);

      Frame();

    protected:
      virtual VOID  onEraseBackground(Event::EraseBackgroundEvent& iEvent);
      virtual VOID  onCreate(Event::WndCreateEvent& iEvent);
      virtual VOID  onDestroy();
      virtual VOID  onCommand(Event::CommandEvent& iEvent);
      virtual VOID  onNotify(Event::NotifyEvent& iEvent);
      virtual VOID  onSize(Event::SizeEvent& iEvent);
      virtual VOID  onSizing(Event::SizingEvent& iEvent);
      virtual VOID  onActivateApp(Event::ActivateAppEvent& iEvent);
      virtual VOID  onMouseDown(Event::MouseEvent& iEvent);
      virtual VOID  onMouseUp(Event::MouseEvent& iEvent);
      virtual VOID  onMouseMove(Event::MouseEvent& iEvent);
      virtual VOID  onClose();

      VOID      initProject();
      VOID      uninitProject();

      VOID      attachDebugger();
      VOID      detachDebugger();
      VOID      closePlayer();

    public:
      VOID      saveResource();
      Data::Resource* createResource(Data::ResourceType iType);
      VOID      editResource(Data::Resource* value);
      VOID      deleteResource(Data::Resource* value);
      VOID      recoverResource(Data::Resource* value);
      VOID      saveResource(Data::Resource* value);
      VOID      showProperties(Data::Resource* value);
      VOID      renameResource(Data::Resource* value, PCTSTR iName);
      VOID      setResourceChanged(Data::Resource* value);

      BOOL      canCloseProject();
      BOOL      canStopProject();
      VOID      saveProject();
      BOOL      openProject();
      VOID      loadProject();
      VOID      closeProject();
      VOID      newProject();
      VOID      updateTitle();
      VOID      showProperties(Data::RetroProject* project);

      VOID      loadState();
      VOID      saveState();

      VOID      runProject();
      VOID      stopProject(BOOL iKill);
      VOID      embedPlayer();
      VOID      detachPlayer();

      VOID      setStatus(FrameComponent iComponent, PCTSTR text);
      VOID      setCanUndo(BOOL canUndo, BOOL canRedo);

      VOID      setHideToolbar(BOOL iHide);
      VOID      setHideStatusbar(BOOL iHide);
      VOID      setHideMenubar(BOOL iHide);

      INL VOID  doLayout()
      {
        mLayout.doLayout();
        updateWindows();
      }

      VOID      doAction(FrameAction action);
      VOID      updateWindows();

      Editor::EditorBase*       findEditor(Data::Resource* iValue);

      INL Editor::EditorBase*   getEditor()
      {
        return mEditor;
      }
      INL Data::Resource*       getResource()
      {
        return mResource;
      }
      INL Hierarchy*            getHierarchy()
      {
        return &mHierarchy;
      }
      INL Editor::EditSurface*  getSurface()
      {
        return &mSurface;
      }
      INL Toolbox::Scriptor*    getScriptor()
      {
        return &mScriptor;
      }
      INL Toolbox::SpriteList*  getSpriteList()
      {
        return &mSprites;
      }
      INL Toolbox::Selector*    getSelector()
      {
        return &mSelector;
      }
      INL LayoutElement*        getRoot()
      {
        return &mLayout;
      }
      INL LayoutElement*        getContent()
      {
        return mWorkspace;
      }
      INL Data::RetroProject&   getProject()
      {
        return project;
      }
      INL GUI::Container*       getActiveCont()
      {
        return mActiveContainer;
      }
      INL Controls::ThemeStyle  getTheme()
      {
        return mTheme;
      }
      INL FrameState&           getState()
      {
        return mState;
      }

      VOID  setTheme(Controls::ThemeStyle iValue);
      VOID  setActiveCont(GUI::Container* value);

      static INL Frame*   get() { return pFrame; }
      static WPARAM       start(LPCTSTR filename);
      static VOID         setWorkingDirectory();
    };
  } // namespace Creator
} // namespace Retro

#endif